package com.novell.sasl.client;

import java.util.ArrayList;
import java.util.Iterator;
import org.apache.harmony.javax.security.sasl.SaslException;

class DigestChallenge
{
  private static final int CIPHER_3DES = 1;
  private static final int CIPHER_DES = 2;
  private static final int CIPHER_RC4 = 8;
  private static final int CIPHER_RC4_40 = 4;
  private static final int CIPHER_RC4_56 = 16;
  private static final int CIPHER_RECOGNIZED_MASK = 31;
  private static final int CIPHER_UNRECOGNIZED = 32;
  public static final int QOP_AUTH = 1;
  public static final int QOP_AUTH_CONF = 4;
  public static final int QOP_AUTH_INT = 2;
  public static final int QOP_UNRECOGNIZED = 8;
  private String m_algorithm;
  private String m_characterSet;
  private int m_cipherOptions;
  private int m_maxBuf;
  private String m_nonce;
  private int m_qop;
  private ArrayList m_realms = new ArrayList(5);
  private boolean m_staleFlag;

  DigestChallenge(byte[] paramArrayOfByte)
    throws SaslException
  {
    this.m_nonce = null;
    this.m_qop = 0;
    this.m_staleFlag = false;
    this.m_maxBuf = -1;
    this.m_characterSet = null;
    this.m_algorithm = null;
    this.m_cipherOptions = 0;
    DirectiveList localDirectiveList = new DirectiveList(paramArrayOfByte);
    try
    {
      localDirectiveList.parseDirectives();
      checkSemantics(localDirectiveList);
      return;
    }
    catch (SaslException localSaslException)
    {
    }
  }

  void checkSemantics(DirectiveList paramDirectiveList)
    throws SaslException
  {
    Iterator localIterator = paramDirectiveList.getIterator();
    if (!(localIterator.hasNext()))
    {
      if (-1 == this.m_maxBuf)
        this.m_maxBuf = 65536;
      if (this.m_qop != 0)
        break label202;
      this.m_qop = 1;
    }
    do
    {
      while (true)
      {
        ParsedDirective localParsedDirective;
        String str;
        do
          while (true)
          {
            while (true)
            {
              while (true)
              {
                while (true)
                {
                  while (true)
                  {
                    while (true)
                    {
                      while (true)
                      {
                        return;
                        localParsedDirective = (ParsedDirective)localIterator.next();
                        str = localParsedDirective.getName();
                        if (!(str.equals("realm")))
                          break;
                        handleRealm(localParsedDirective);
                      }
                      if (!(str.equals("nonce")))
                        break;
                      handleNonce(localParsedDirective);
                    }
                    if (!(str.equals("qop")))
                      break;
                    handleQop(localParsedDirective);
                  }
                  if (!(str.equals("maxbuf")))
                    break;
                  handleMaxbuf(localParsedDirective);
                }
                if (!(str.equals("charset")))
                  break;
                handleCharset(localParsedDirective);
              }
              if (!(str.equals("algorithm")))
                break;
              handleAlgorithm(localParsedDirective);
            }
            if (!(str.equals("cipher")))
              break;
            handleCipher(localParsedDirective);
          }
        while (!(str.equals("stale")));
        handleStale(localParsedDirective);
      }
      if ((0x1 & this.m_qop) != 1)
        label202: throw new SaslException("Only qop-auth is supported by client");
      if (((0x4 & this.m_qop) == 4) && ((0x1F & this.m_cipherOptions) == 0))
        throw new SaslException("Invalid cipher options");
      if (this.m_nonce == null)
        throw new SaslException("Missing nonce directive");
      if (this.m_staleFlag)
        throw new SaslException("Unexpected stale flag");
    }
    while (this.m_algorithm != null);
    throw new SaslException("Missing algorithm directive");
  }

  public String getAlgorithm()
  {
    return this.m_algorithm;
  }

  public String getCharacterSet()
  {
    return this.m_characterSet;
  }

  public int getCipherOptions()
  {
    return this.m_cipherOptions;
  }

  public int getMaxBuf()
  {
    return this.m_maxBuf;
  }

  public String getNonce()
  {
    return this.m_nonce;
  }

  public int getQop()
  {
    return this.m_qop;
  }

  public ArrayList getRealms()
  {
    return this.m_realms;
  }

  public boolean getStaleFlag()
  {
    return this.m_staleFlag;
  }

  void handleAlgorithm(ParsedDirective paramParsedDirective)
    throws SaslException
  {
    if (this.m_algorithm != null)
      throw new SaslException("Too many algorithm directives.");
    this.m_algorithm = paramParsedDirective.getValue();
    if (!("md5-sess".equals(this.m_algorithm)))
      throw new SaslException("Invalid algorithm directive value: " + this.m_algorithm);
  }

  void handleCharset(ParsedDirective paramParsedDirective)
    throws SaslException
  {
    if (this.m_characterSet != null)
      throw new SaslException("Too many charset directives.");
    this.m_characterSet = paramParsedDirective.getValue();
    if (!(this.m_characterSet.equals("utf-8")))
      throw new SaslException("Invalid character encoding directive");
  }

  void handleCipher(ParsedDirective paramParsedDirective)
    throws SaslException
  {
    if (this.m_cipherOptions != 0)
      throw new SaslException("Too many cipher directives.");
    TokenParser localTokenParser = new TokenParser(paramParsedDirective.getValue());
    localTokenParser.parseToken();
    String str = localTokenParser.parseToken();
    if (str == null)
    {
      if (this.m_cipherOptions == 0)
        this.m_cipherOptions = 32;
      return;
    }
    if ("3des".equals(str))
      this.m_cipherOptions = (0x1 | this.m_cipherOptions);
    while (true)
    {
      while (true)
      {
        while (true)
        {
          while (true)
          {
            while (true)
            {
              while (true)
                str = localTokenParser.parseToken();
              if (!("des".equals(str)))
                break;
              this.m_cipherOptions = (0x2 | this.m_cipherOptions);
            }
            if (!("rc4-40".equals(str)))
              break;
            this.m_cipherOptions = (0x4 | this.m_cipherOptions);
          }
          if (!("rc4".equals(str)))
            break;
          this.m_cipherOptions = (0x8 | this.m_cipherOptions);
        }
        if (!("rc4-56".equals(str)))
          break;
        this.m_cipherOptions = (0x10 | this.m_cipherOptions);
      }
      this.m_cipherOptions = (0x20 | this.m_cipherOptions);
    }
  }

  void handleMaxbuf(ParsedDirective paramParsedDirective)
    throws SaslException
  {
    if (-1 != this.m_maxBuf)
      throw new SaslException("Too many maxBuf directives.");
    this.m_maxBuf = Integer.parseInt(paramParsedDirective.getValue());
    if (this.m_maxBuf == 0)
      throw new SaslException("Max buf value must be greater than zero.");
  }

  void handleNonce(ParsedDirective paramParsedDirective)
    throws SaslException
  {
    if (this.m_nonce != null)
      throw new SaslException("Too many nonce values.");
    this.m_nonce = paramParsedDirective.getValue();
  }

  void handleQop(ParsedDirective paramParsedDirective)
    throws SaslException
  {
    if (this.m_qop != 0)
      throw new SaslException("Too many qop directives.");
    TokenParser localTokenParser = new TokenParser(paramParsedDirective.getValue());
    String str = localTokenParser.parseToken();
    if (str == null)
      return;
    if (str.equals("auth"))
      this.m_qop = (0x1 | this.m_qop);
    while (true)
    {
      while (true)
      {
        while (true)
        {
          while (true)
            str = localTokenParser.parseToken();
          if (!(str.equals("auth-int")))
            break;
          this.m_qop = (0x2 | this.m_qop);
        }
        if (!(str.equals("auth-conf")))
          break;
        this.m_qop = (0x4 | this.m_qop);
      }
      this.m_qop = (0x8 | this.m_qop);
    }
  }

  void handleRealm(ParsedDirective paramParsedDirective)
  {
    this.m_realms.add(paramParsedDirective.getValue());
  }

  void handleStale(ParsedDirective paramParsedDirective)
    throws SaslException
  {
    if (this.m_staleFlag)
      throw new SaslException("Too many stale directives.");
    if ("true".equals(paramParsedDirective.getValue()))
    {
      this.m_staleFlag = true;
      return;
    }
    throw new SaslException("Invalid stale directive value: " + paramParsedDirective.getValue());
  }
}